<?php
namespace app\common\model;

use think\Config;
use think\exception\PDOException;
use think\Log;
use think\Model;

class BaseModel extends Model
{
    /**
     * 返回状态码.
     *
     * @var int
     */
    public $code = 1;

    /**
     * 返回结果.
     *
     * @var string
     */
    public $msg = 'success';

    /**
     * 数据结果.
     *
     * @var array
     */
    public $returnData = [];

    /**
     * 返回数据（包含：code,msg,returnData）.
     *
     * @var array
     */
    public $return;

    /**
     * 日志记录类型.
     *
     * @var string
     */
    protected $logType = 'notice';

    /**
     * 当前商家id.
     *
     * @var int
     */
    protected $currentBid;

    /**
     * 数据库配置.
     *
     * @var array
     */
    protected $dbConfig;

    /**
     * BaseModel constructor.
     *
     * @param array $data
     */
    public function __construct($data = [])
    {
//        $this->currentBid = isset($data['bid']) ? (int) $data['bid'] : 1;
//        $this->dbConfig = 'pro' === get_cfg_var('minicart.env') ? 'db_pro' : 'db_dev';
//        $this->connection = config($this->dbConfig.'.db_business'.$this->currentBid);
        $this->return = [
            'code' => &$this->code,
            'msg' => &$this->msg,
            'data' => &$this->returnData,
        ];
        parent::__construct($data);
    }

    /**
     * 获取Db异常错误码.
     *
     * @param $e
     *
     * @return int
     */
    public function getErrorCode($e)
    {
        if ($e instanceof PDOException) {
            $this->code = $e->getData()['PDO Error Info']['Driver Error Code'];

            return  $this->code;
        }

        return 0;
    }

    //单条查询 返回数组
    public function only($where = [], $field = '*', $with = '')
    {
        if ($with) {
            $result = $this->with($with)->where($where)->field($field)->find();
        } else {
            $result = $this->where($where)->field($field)->find();
        }
        if ($result) {
            return $result->toArray();
        }

        return false;
    }

    //查询所有 返回数组
    public function whole($where = [], $field = '*', $order = 'id asc', $with = '')
    {
        if ($with) {
            $result = $this->with($with)->where($where)->field($field)->order($order)->select();
        } else {
            $result = $this->where($where)->field($field)->order($order)->select();
        }

        return $result->toArray();
    }

    //删除 bool
    public function del($where = [])
    {
        return $this->where($where)->delete();
    }

    //更新 返回ID
    public function up($data, $where = [])
    {
        $this->save($data, $where);

        return $this->id;
    }

    //更新OR新增 返回数组
    public function saves($data, $bool)
    {
        $this->isUpdate($bool)->save($data);

        return $this->id;
    }

    /**
     * 保存多个数据到当前数据对象(更新插入).
     *
     * @param array $dataSet 数据
     * @param bool  $replace 是否自动识别更新和写入(更新插入) on duplicate key
     *
     * @throws \Exception
     *
     * @return array|false
     */
    public function _insertAllUpdate($dataSet, $replace = true)
    {
        if ($this->validate) {
            // 数据批量验证
            $validate = $this->validate;
            foreach ($dataSet as $data) {
                if (!$this->validateData($data, $validate)) {
                    return false;
                }
            }
        }

        // 不知道为什么TP5把on duplicate key去掉了。。。
        $result = [];
        $db = $this->getQuery();
        $db->fetchSql();
        $sql = $db->insertAll($dataSet, false);

        $updateFields = [];
        if (\is_array($replace)) {
            $updateFields = $replace;
        } elseif (true === $replace) {
            $updateFields = array_keys(current($dataSet));
        }
        if (!empty($updateFields)) {
            $update = ' on duplicate key update ';
            foreach ($updateFields as $field) {
                $update .= '`'.$field.'`=values(`'.$field.'`),';
            }
            $update = substr($update, 0, -1);
            $sql = ($sql.' '.$update);
        }

        $db->fetchSql(false);

        try {
            if (false === $db->execute($sql)) {
                $this->error = '非法数据！';

                return false;
            }

            return true;
        } catch (\Exception $e) {
            throw $e;
        }

        return false;
    }

    /**
     * 错误与异常消息处理.
     *
     * @param $e object 抛出异常的对象
     * @param $data array 参数信息
     * @param $record bool 是否需要记录日志信息
     */
    protected function errorMessage($e, $data = [], $record = true)
    {
        if (($e instanceof \think\Exception)) {
            $this->msg = $e->getMessage();
            $this->code = $e->getCode();
            //防止系统错误信息直接暴露
            if ('40' !== mb_substr($e->getCode(), 0, 2)) {
                $errorData = Config::get('error.SYSTEM_ERROR');
                $this->msg = $errorData['msg'];
                $this->code = $errorData['code'];
                $this->logType = 'error';
            }
            if ($record) {
                $errorMsg = $e->getMessage().' 在 '.$e->getFile().' '.$e->getLine().' 行'.PHP_EOL.$e->getTraceAsString();
                $errorMsg .= !empty($data) ? ' 相关参数：'.json_encode($data, JSON_UNESCAPED_UNICODE) : '';
                Log::record($errorMsg, $this->logType);
            }
        }
    }
}
